package com.gopay.bis.hxbc.ebank.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.bank.HxbcConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.hxbc.ebank.HXBCMessage;
import com.gopay.common.domain.bank.hxbc.ebank.geturl.res.BodyB2CResGetUrl;
import com.gopay.common.domain.bank.hxbc.ebank.geturl.res.HXEB2CResGetUrl;
import com.gopay.common.domain.bank.hxbc.ebank.geturl.res.SicB2CResGetUrl;
import com.gopay.common.domain.bank.hxbc.ebank.geturl.res.VerifySignB2CResGetUrl;
import com.gopay.common.domain.bank.hxbc.ebank.geturl.res.VerifySignSucBodyB2CResGetUrl;
import com.gopay.common.domain.bank.hxbc.ebank.pay.req.HXEB2CReqPay;
import com.gopay.common.domain.bank.hxbc.ebank.pay.req.HXEB2CReqPayCheck;
import com.gopay.common.domain.bank.hxbc.ebank.pay.req.HeadB2CReqPayCheck;
import com.gopay.common.domain.bank.hxbc.ebank.pay.res.BackHXEB2CResPay;
import com.gopay.common.domain.bank.hxbc.ebank.pay.res.BackSicB2CResPay;
import com.gopay.common.domain.bank.hxbc.ebank.pay.res.BackVerifyB2CResPay;
import com.gopay.common.domain.bank.hxbc.ebank.pay.res.BackVerifySucBodyB2CResPay;
import com.gopay.common.domain.bank.hxbc.ebank.pay.res.ForeVerifyB2CResPay;
import com.gopay.common.domain.bank.hxbc.ebank.query.req.HXEB2CReqQuery;
import com.gopay.common.domain.bank.hxbc.ebank.query.res.HXEB2CResQuery;
import com.gopay.common.domain.bank.hxbc.ebank.query.res.SicB2CResQuery;
import com.gopay.common.domain.bank.hxbc.ebank.query.res.VerifySignB2CResQuery;
import com.gopay.common.domain.bank.hxbc.ebank.query.res.VerifySignSucBodyB2CResQuery;
import com.gopay.common.domain.bank.hxbc.ebank.res.HeadB2CRes;
import com.gopay.common.domain.bank.hxbc.ebank.sign.res.SignHXEB2CRes;
import com.gopay.common.domain.bank.hxbc.ebank.sign.res.SignSucBodyB2CRes;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.ICertHelperHxbc;
import com.gopay.remote.bank.businesses.BankService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 华夏签名/验签接口实现
 * 
 * @HxbcB2cBankServiceImpl.java
 * @author LiLiLi
 */
public class HxbcB2cBankServiceImpl implements BankService {

	private ICertHelperHxbc hxbcB2cCerthelper;
	private final static Logger logger = LoggerFactory
			.getLogger("HxbcB2cBankServiceImpl");

	@Override
	public Object sign(BaseMessage msg) throws GopayException {
		HXEB2CReqPay messageB2C = (HXEB2CReqPay) msg;
		HXBCMessage hxbcMessage = new HXBCMessage();
		hxbcMessage.setPlainMessage(messageB2C.getPlainMessage());
		String sign = this.hxbcB2cCerthelper.sign(hxbcMessage);
		XStream xstream = new XStream(new DomDriver());
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(SignHXEB2CRes.class);
		SignHXEB2CRes hxeRes = (SignHXEB2CRes) xstream.fromXML(sign);
		SignSucBodyB2CRes bodyRes = hxeRes.getBody();
		hxbcMessage.setSignMessage(bodyRes.getSign());
		String signMessage = this.hxbcB2cCerthelper.signToBank(hxbcMessage);
		BankLogUtils.printB2CSignSignatureLog(hxbcMessage, signMessage);
		hxbcMessage.setSignMessage(signMessage);
		String plainMessage = (String) this.hxbcB2cCerthelper
				.verify(hxbcMessage);
		logger.info("plainMessage=========" + plainMessage);
		XStream xstreamVerify = new XStream(new DomDriver());
		xstreamVerify.autodetectAnnotations(true);
		xstreamVerify.processAnnotations(VerifySignB2CResGetUrl.class);
		VerifySignB2CResGetUrl verifyRes = (VerifySignB2CResGetUrl) xstreamVerify
				.fromXML(plainMessage);
		VerifySignSucBodyB2CResGetUrl bodyResVerify = verifyRes.getBody();
		SicB2CResGetUrl sicRes = bodyResVerify.getSic();
		HXEB2CResGetUrl sicHxeRes = sicRes.getHXE();
		BodyB2CResGetUrl sicBodyRes = sicHxeRes.getBody();
		sicHxeRes.setBankUrl(sicBodyRes.getURL());
		return sicHxeRes;
	}

	@Override
	public Object verify(BaseMessage msg) throws GopayException {
		HXBCMessage hxbcMessage = new HXBCMessage();
		HXEB2CReqPay messageB2C = (HXEB2CReqPay) msg;
		if (!messageB2C.isFront()) {
			// 后台通知验签处理
			String signMessage = messageB2C.getSignMessage();
			hxbcMessage.setSignMessage(signMessage);
			BankLogUtils.printB2CVerifySignatureLog(hxbcMessage, signMessage);
			/**
			 * 获取明文
			 */
			String plaintxt = (String) this.hxbcB2cCerthelper
					.verify(hxbcMessage);
			/**
			 * 设置信息对应明文串
			 */
			hxbcMessage.setPlainMessage(plaintxt);
			BankLogUtils.printB2CVerifyPlainLog(hxbcMessage);
			XStream xstream = new XStream(new DomDriver());
			xstream.autodetectAnnotations(true);
			xstream.processAnnotations(BackVerifyB2CResPay.class);
			BackVerifyB2CResPay verifyRes = (BackVerifyB2CResPay) xstream
					.fromXML(plaintxt);
			BackVerifySucBodyB2CResPay bodyRes = verifyRes.getBody();
			BackSicB2CResPay sicRes = bodyRes.getSic();
			BackHXEB2CResPay sicHxeRes = sicRes.getHXE();
			HeadB2CRes sicHeadRes = sicHxeRes.getHead();
			// 组装报文，通知银行交易结果
			HXEB2CReqPayCheck payCheck = new HXEB2CReqPayCheck();
			HeadB2CReqPayCheck headCheck = new HeadB2CReqPayCheck();
			headCheck.setIdentification(sicHeadRes.getIdentification());
			headCheck.setTrnxCode("T" + sicHeadRes.getTrnxCode());
			headCheck.setTrnxDatetime(sicHeadRes.getTrnxDatetime());
			headCheck.setRespCode(sicHeadRes.getRespCode());
			headCheck.setRespDecp(sicHeadRes.getRespDescp());
			payCheck.setHead(headCheck);
			XStream xs = new XStream(new DomDriver());
			xs.autodetectAnnotations(true);
			xs.processAnnotations(HXEB2CReqPayCheck.class);
			String plainStr = xs.toXML(payCheck);
			hxbcMessage.setPlainMessage(plainStr);
			String sign = hxbcB2cCerthelper.sign(hxbcMessage);
			XStream sxs = new XStream(new DomDriver());
			sxs.autodetectAnnotations(true);
			sxs.processAnnotations(SignHXEB2CRes.class);
			SignHXEB2CRes hxeRes = (SignHXEB2CRes) sxs.fromXML(sign);
			SignSucBodyB2CRes signBodyRes = hxeRes.getBody();
			String returnSignMessage = signBodyRes.getSign();
			BankLogUtils.printB2CVerifySignatureLog(hxbcMessage,
					returnSignMessage);
			hxbcMessage.setSignMessage(returnSignMessage);
			hxbcB2cCerthelper.signToBank(hxbcMessage);
			return verifyRes;
		} else if (messageB2C.isFront()) {
			// 前台通知验签处理
			String signMessage = messageB2C.getSignMessage();
			logger.info("前台验签字符串：signMessage========"+signMessage);
			BankLogUtils.printB2CVerifySignatureLog(hxbcMessage, signMessage);
			hxbcMessage.setSignMessage(signMessage);
			String plaintxt = (String) this.hxbcB2cCerthelper
					.verify(hxbcMessage);
			logger.info("前台验签后明文报文：plaintxt========"+plaintxt);
			hxbcMessage.setPlainMessage(plaintxt);
			BankLogUtils.printB2CVerifyPlainLog(hxbcMessage);
			XStream xstream = new XStream(new DomDriver());
			xstream.autodetectAnnotations(true);
			xstream.processAnnotations(ForeVerifyB2CResPay.class);
			ForeVerifyB2CResPay verifyRes = (ForeVerifyB2CResPay) xstream
					.fromXML(plaintxt);
			return verifyRes;
		} else {
			// 不匹配
			BankLogUtils.printB2CVerifyExceptionLog(hxbcMessage, new Exception(
					"not matches"));
			return null;
		}

	}

	@Override
	public Object query(Object obj) throws GopayException {
		HXBCMessage hxbcMessage = new HXBCMessage();
		HXEB2CReqQuery messageB2CQuery = (HXEB2CReqQuery) obj;
		String param = messageB2CQuery.getPlainMessage();
		hxbcMessage.setPlainMessage(param);
		BankLogUtils.printB2CQuerySendLog(hxbcMessage, param);
		String signMessage = this.hxbcB2cCerthelper.sign(hxbcMessage);
		XStream xstream = new XStream(new DomDriver());
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(SignHXEB2CRes.class);
		SignHXEB2CRes hxeRes = (SignHXEB2CRes) xstream.fromXML(signMessage);
		SignSucBodyB2CRes bodyRes = hxeRes.getBody();
		String returnSignMessage = bodyRes.getSign();
		hxbcMessage.setSignMessage(returnSignMessage);
		String verifySign = this.hxbcB2cCerthelper.signToBank(hxbcMessage);
		hxbcMessage.setSignMessage(verifySign);
		String plainMessage = (String) this.hxbcB2cCerthelper
				.verify(hxbcMessage);
		BankLogUtils.printB2CQueryBlackLog(hxbcMessage, plainMessage);
		if (plainMessage.indexOf("<sic>") >= 0) {
			if (plainMessage.contains("<Body>")) {
				// 订单信息
				XStream xstreamQuery = new XStream(new DomDriver());
				xstreamQuery.autodetectAnnotations(true);
				xstreamQuery.processAnnotations(VerifySignB2CResQuery.class);
				VerifySignB2CResQuery verifyRes = (VerifySignB2CResQuery) xstreamQuery
						.fromXML(plainMessage);
				VerifySignSucBodyB2CResQuery bodyResQuery = verifyRes.getBody();
				SicB2CResQuery sicRes = bodyResQuery.getSic();
				HXEB2CResQuery sicHxeRes = sicRes.getHXE();
				return sicHxeRes;
			} else {
				// 无此记录
				HeadB2CRes headRes = new HeadB2CRes();
				headRes.setRespCode(HxbcConstants.RESPCODE_NOTFOUND);
				HXEB2CResQuery sicHxeRes = new HXEB2CResQuery();
				sicHxeRes.setHead(headRes);
				return sicHxeRes;
			}
		} else {
			// 验签出错
			HeadB2CRes headRes = new HeadB2CRes();
			headRes.setRespCode(HxbcConstants.RESPCODE_OTHER);
			HXEB2CResQuery sicHxeRes = new HXEB2CResQuery();
			sicHxeRes.setHead(headRes);
			return sicHxeRes;
		}
	}

	public void setHxbcB2cCerthelper(ICertHelperHxbc hxbcB2cCerthelper) {
		this.hxbcB2cCerthelper = hxbcB2cCerthelper;
	}

	@Override
	public Object dayend(Object obj) throws GopayException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object refund(Object obj) throws GopayException {
		// TODO Auto-generated method stub
		return null;
	}

}
